/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.andremion.louvre.loader;

import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.app.Context;
import ohos.data.dataability.DataAbilityPredicates;
import ohos.data.resultset.CombinedResultSet;
import ohos.data.resultset.ResultSet;
import ohos.data.resultset.TableResultSet;
import ohos.media.photokit.metadata.AVStorage;

import java.util.Arrays;

/**
 * ResultSetLoader
 */
public class ResultSetLoader {
    /**
     * ITEM_ID_CAPTURE
     */
    public static final long ITEM_ID_CAPTURE = -1;
    /**
     * ITEM_DISPLAY_NAME_CAPTURE
     */
    public static final String ITEM_DISPLAY_NAME_CAPTURE = "Capture";
    private static final String COLUMN_BUCKET_ID = "_id";
    private static String[] mImageType = new String[]{"image/jpeg", "image/png", "image/bmp"};
    private static String mImageTypeQuery = AVStorage.AVBaseColumns.MIME_TYPE + "=?"
            + " OR " + AVStorage.AVBaseColumns.MIME_TYPE + "=?"
            + " OR " + AVStorage.AVBaseColumns.MIME_TYPE + "=?"
            + " AND " + AVStorage.AVBaseColumns.SIZE + ">0";

    private static final String[] PROJECTION = {
            AVStorage.AVBaseColumns.ID,
            COLUMN_BUCKET_ID,
            AVStorage.AVBaseColumns.DISPLAY_NAME,
            AVStorage.AVBaseColumns.MIME_TYPE,
            AVStorage.AVBaseColumns.SIZE,
            AVStorage.AVBaseColumns.DATA,
            AVStorage.AVBaseColumns.DURATION};

    // ===========================================================

    /**
     * setSelectionArgsForSingleMediaType
     *
     * @param mImageType mImageType Array
     */
    public void setSelectionArgsForSingleMediaType(String[] mImageType) {
        if (mImageType != null && mImageType.length > 0) {
            this.mImageType = mImageType;
        }
        if (mImageType.length == 1) {
            mImageTypeQuery = AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " AND " + AVStorage.AVBaseColumns.SIZE + ">0";

        } else if (mImageType.length == 2) {
            mImageTypeQuery = AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " OR " + AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " AND " + AVStorage.AVBaseColumns.SIZE + ">0";

        } else {
            mImageTypeQuery = AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " OR " + AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " OR " + AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " AND " + AVStorage.AVBaseColumns.SIZE + ">0";
        }
    }

    private Context mContext;
    private ResultSetLoaderTask loaderTask;
    private LoaderCallback<ResultSet> loaderCallback;
    private boolean mCapture = false;

    /**
     * setContext
     *
     * @param mContext Context
     */
    public void setContext(Context mContext) {
        this.mContext = mContext;
    }

    /**
     * getContext
     *
     * @return mContext Context
     */
    public Context getContext() {
        return mContext;
    }

    public ResultSetLoader(Context mContext) {
        this.mContext = mContext;
    }

    public ResultSetLoader(Context mContext, boolean mCapture) {
        this.mContext = mContext;
        this.mCapture = mCapture;
    }

    private void newLoad(boolean mCapture) {
        this.mCapture = mCapture;
        String selection;
        String[] selectionArgs;
        selection = mImageTypeQuery;
        selectionArgs =
                mImageType;

        loaderTask = new ResultSetLoaderTask(selection, selectionArgs);
    }

    /**
     * setLoaderCallback
     *
     * @param loaderCallback loaderCallback
     */
    public void setLoaderCallback(LoaderCallback<ResultSet> loaderCallback) {
        this.loaderCallback = loaderCallback;
    }

    /**
     * load
     */
    public void load() {
        newLoad(mCapture);
        loaderTask.execute();
    }

    /**
     * cancel
     *
     * @param interruptlf Boolean
     */
    public void cancel(boolean interruptlf) {
        if (interruptlf) {
            loaderCallback = null;
        }
        if (loaderTask != null) {
            loaderTask.cancel(interruptlf);
        }
    }

    class ResultSetLoaderTask extends AsyncTaskLoader<String, ResultSet> {
        private String selection;
        private String[] selectionArgs;

        ResultSetLoaderTask(String selection, String[] selectionArgs) {
            this.selection = selection;
            this.selectionArgs = selectionArgs;
        }

        @Override
        protected ResultSet doInBackground(String[] strings) {
            ResultSet resultSet = null;
            try {
                DataAbilityHelper helper = DataAbilityHelper.creator(getContext());
                if (selection == null) {
                    resultSet = helper.query(AVStorage.Files.fetchResource("external"), PROJECTION, null);
                } else {
                    DataAbilityPredicates predicates = new DataAbilityPredicates(selection);
                    predicates.setWhereArgs(Arrays.asList(selectionArgs));
                    resultSet = helper.query(AVStorage.Files.fetchResource("external"), PROJECTION, predicates);
                }

                if (mCapture) {
                    TableResultSet dummy = new TableResultSet(PROJECTION);
                    dummy.addRow(new Object[]{ITEM_ID_CAPTURE, ITEM_DISPLAY_NAME_CAPTURE, "image/jpeg", 0, "", 0});
                    helper.release();
                    return new CombinedResultSet(new ResultSet[]{dummy, resultSet});
                } else {
                    helper.release();
                    return resultSet;
                }
            } catch (DataAbilityRemoteException dataAbilityRemoteException) {
                return resultSet;
            }
        }

        @Override
        protected void postResult(ResultSet albums) {
            super.postResult(albums);
            if (loaderCallback != null && albums != null) {
                loaderCallback.setCallback(albums);
            }
        }
    }
}
